package top.jnaw.jee.platform.model;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import top.jnaw.jee.platform.Consts;
import top.jnaw.jee.platform.Consts.Result;
import top.jnaw.jee.platform.model.base.BaseApproval;
import top.jnaw.jee.utils.ApprovalUtil;
import top.jnaw.jee.utils.Log;
import top.jnaw.jee.utils.ModelResult;
import top.jnaw.jee.utils.Models;
import top.jnaw.jee.utils.Strings;

/**
 * Generated by JFinal.
 */
@SuppressWarnings("serial")
public class Approval extends BaseApproval<Approval> {

  public static final Approval dao = new Approval().dao();

  public static ModelResult add(int wid, int tid, String title,
      JSONArray process, JSONObject data) {
    ModelResult result = new ModelResult(Result.kBadParam);

    if (tid > 0 && wid > 0) {
      ApprovalTemplate template = ApprovalTemplate.dao.findById(tid);
      if (null != template) {
        if (process != null && process.size() > 0) {
          for (int i = process.size(); i < template.getTotal(); i++) {
            process.add(i,
                Strings.toJSONArray(template.getProcess()).getJSONObject(i));
          }
        } else {
          process = Strings.toJSONArray(template.getProcess());
        }
        Approval approval = new Approval();
        approval.setWid(wid);
        approval.setTitle(title);
        if (null != data) {
          approval.setData(data.toJSONString());
        }
        approval.setType(template.getType());
        approval.setTotal(template.getTotal());
        boolean r = approval.save();
        if (r) {
          result = ApprovalRecords.add(approval.getId(), process);
        }
        if (result.fine()) {
          //新审批推送
          ApprovalUtil.urge(approval.getId());
          result.setObject(approval);
        }
      }
    }
    return result;
  }

  public static boolean delete(int id) {
    return dao.deleteById(id);
  }

  public static ModelResult getPreviewId(int aid, String type) {
    ModelResult result = new ModelResult(Result.kNull);

    if (StrKit.notBlank(type)) {

      String sql = Db.getSql("approval-Preview").replace("table", type);
      Record record = Db.findFirst(sql, aid);

      if (record != null) {
        JSONObject object = new JSONObject();
        object.put("id", record.getInt("id"));
        result.setObject(object);
        result.setResult(Result.kSuccess);
      }
    }

    return result;
  }

  /**
   * 根据审批id 获取推送人员列表
   */
  public static List<Users> getPushUserList(int aid) {

    LinkedHashSet<Integer> uids = new LinkedHashSet<>();

    List<ApprovalRecords> records = ApprovalRecords.getList(aid);

    for (ApprovalRecords record : records) {
      uids.add(record.getApprover());
    }
    if (uids.size() <= 0) {
      uids.add(-1);
    }
    String uidStr = Strings
        .genInClause(uids.toArray(Consts.EMPTY_INTEGER_ARRAY));

    return Users.list(uidStr);
  }

  /**
   * 根据审批id获取当前审批节点的推送人员
   */
  public static JSONArray getCurrentApprovers(int aid) {
    JSONArray array = new JSONArray();
    Approval approval = dao.findById(aid);
    if (null != approval) {
      int stage = approval.getStage();
      Log.e("stage:" + stage);
      List<ApprovalRecords> list = ApprovalRecords.list(aid, stage);
      for (ApprovalRecords ar : list) {
        JSONObject object = getJpush(ar.getApprover());
        array.add(object);
      }
    }
    return array;
  }

  private static JSONObject getJpush(int uid) {
    JSONObject object = new JSONObject();
    Users user = Users.dao.findById(uid);
    object.put("id", user.getId());
    object.put("mobile", user.getMobile());
    object.put("username", user.getUsername());
    if (null != user.getAvatar() && user.getAvatar() > 0) {
      Files files = Files.dao.findById(user.getAvatar());
      if (null != files) {
        object.put("thumb", files.getThumb());
      }
    } else {
      object.put("thumb", null);
    }
    return object;
  }

  public static ModelResult update(int uid, int id, String status,
      String content, JSONArray accessory, int did) {
    ModelResult result = new ModelResult(Result.kNull);

    Approval approval = dao.findById(id);
    if (null != approval) {
      int stage = approval.getStage();
      int total = approval.getTotal();

      result.setResult(Result.kBadCheck);
      if (Consts.APPROVAL_CHECKING.equals(approval.getStatus())) {

        result = ApprovalRecords.update(uid, id, stage, status, content);
        if (result.fine()) {
          ApprovalRecords record = (ApprovalRecords) result.getObject();
          if (null != record) {
            switch (record.getStatus()) {
              case Consts.APPROVAL_PASSED:
                approval.setLastModifyTime(new Date());

                if (stage == total) {
                  approval.setStatus(Consts.APPROVAL_PASSED);
                } else {
                  approval.setStage(stage + 1);

                  //调解转到对应的街道
                  if ("mediation".equals(approval.getType())) {
                    int charge = Department.getCharge(did);
                    if (charge > 0) {
                      ApprovalRecords
                          .add(approval.getId(), charge, stage + 1, 1);
                      Mediation mediation = Mediation.dao
                          .findFirst("select * from mediation where aid=" + id);
                      if (null != mediation) {
                        mediation.setDid(did);
                        mediation.update();
                      }
                    }
                  }

                  JSONArray uids = new JSONArray();
                  List<Users> usersList = new ArrayList<>();
                  List<ApprovalRecords> list = ApprovalRecords.dao
                      .find(Db.getSql("approvalRecords-list-stage"), id,
                          stage + 1);
                  if (null != list && list.size() > 0) {
                    for (ApprovalRecords records : list) {
                      uids.add(records.getApprover());
                    }
                  }

                  if (uids.size() > 0) {
                    usersList = Users.dao.find(
                        "select * from users where id in" + Strings
                            .genInClause(uids));
                  }

                  if (usersList.size() > 0) {
                    //给下一级审批人发推送
                    String title = "审批申请";
                    String alert = String
                        .format(Consts.NIM_NOTIFY_TEMPLATE_UNREAD, "审批");
                    String from = "approval";

                    MessagePush messagePush = new MessagePush(title, alert,
                        from, "", String.valueOf(id), "", "", usersList);
                    messagePush.sendJPush();
                    messagePush.sendNIM();
                  }
                }
                approval.update();
                if (stage == total) {
                  result.setResult(afterPassed(approval)
                                   ? Result.kSuccess
                                   : Result.kException);
                }
                break;

              case Consts.APPROVAL_REJECTED:

                approval.setLastModifyTime(new Date());
                approval.setStatus(Consts.APPROVAL_REJECTED);
                approval.update();
                result.setResult(afterRejected(approval)
                                 ? Result.kSuccess
                                 : Result.kException);
                break;

              case Consts.APPROVAL_CANCEL:

                approval.setLastModifyTime(new Date());
                approval.setStatus(Consts.APPROVAL_CANCEL);
                approval.update();
                result.setResult(afterCancled(approval)
                                 ? Result.kSuccess
                                 : Result.kException);
                break;
              case Consts.APPROVAL_SUCCESS:
                FileModel.add(1, record.getId(), accessory, "accessory");
                approval.setLastModifyTime(new Date());
                approval.setStatus(Consts.APPROVAL_SUCCESS);
                approval.update();
                result.setResult(afterSuccess(approval)
                                 ? Result.kSuccess
                                 : Result.kException);
                break;
              case Consts.APPROVAL_FAIL:

                approval.setLastModifyTime(new Date());
                approval.setStatus(Consts.APPROVAL_FAIL);
                approval.update();
                result.setResult(afterFail(approval)
                                 ? Result.kSuccess
                                 : Result.kException);
                break;

              default:
                Log.e("other approval status");
                break;
            }
          }
        }
      }
    }

    return result;
  }

  private static boolean afterSuccess(Approval approval) {
    ModelResult result = new ModelResult(Result.kNext);
    if (null != approval) {
      switch (approval.getType()) {
        case "land": {
          result = Land.updateStatus(approval.getId(), Consts.APPROVAL_SUCCESS);
          break;
        }
        case "loan": {
          result = Loan.updateStatus(approval.getId(), Consts.APPROVAL_SUCCESS);
          break;
        }
        case "mediation": {
          result = Mediation
              .updateStatus(approval.getId(), Consts.APPROVAL_SUCCESS);
          break;
        }
        default:
          Log.e("other approval todo");
          break;
      }
    }
    return result.fine();
  }

  private static boolean afterFail(Approval approval) {
    ModelResult result = new ModelResult(Result.kNext);
    if (null != approval) {
      switch (approval.getType()) {
        case "land": {
          result = Land.updateStatus(approval.getId(), Consts.APPROVAL_FAIL);
          break;
        }
        case "loan": {
          result = Loan.updateStatus(approval.getId(), Consts.APPROVAL_FAIL);
          break;
        }
        case "mediation": {
          result = Mediation
              .updateStatus(approval.getId(), Consts.APPROVAL_FAIL);
          break;
        }
        default:
          Log.e("other approval todo");
          break;
      }
    }
    return result.fine();
  }

  private static boolean afterCancled(Approval approval) {
    ModelResult result = new ModelResult(Result.kNext);
    if (null != approval) {
      switch (approval.getType()) {
        case "land": {
          result = Land.updateStatus(approval.getId(), Consts.APPROVAL_CANCEL);
          break;
        }
        case "loan": {
          result = Loan.updateStatus(approval.getId(), Consts.APPROVAL_CANCEL);
          break;
        }
        case "mediation": {
          result = Mediation
              .updateStatus(approval.getId(), Consts.APPROVAL_CANCEL);
          break;
        }
        default:
          Log.e("other approval todo");
          break;
      }
    }
    return result.fine();
  }

  private static boolean afterPassed(Approval approval) {
    ModelResult result = new ModelResult(Result.kNext);
    if (null != approval) {
      switch (approval.getType()) {
        case "land": {
          result = Land.updateStatus(approval.getId(), Consts.APPROVAL_PASSED);
          break;
        }
        case "loan": {
          result = Loan.updateStatus(approval.getId(), Consts.APPROVAL_PASSED);
          break;
        }
        case "mediation": {
          result = Mediation
              .updateStatus(approval.getId(), Consts.APPROVAL_PASSED);
          break;
        }
        default:
          Log.e("other approval todo");
          break;
      }
    }
    return result.fine();
  }

  private static boolean afterRejected(Approval approval) {
    ModelResult result = new ModelResult(Result.kNext);
    if (null != approval) {

      switch (approval.getType()) {
        case "land": {
          result = Land
              .updateStatus(approval.getId(), Consts.APPROVAL_REJECTED);
          break;
        }
        case "loan": {
          result = Loan
              .updateStatus(approval.getId(), Consts.APPROVAL_REJECTED);
          break;
        }
        case "mediation": {
          result = Mediation
              .updateStatus(approval.getId(), Consts.APPROVAL_REJECTED);
          break;
        }
        default:
          Log.e("other approval todo");
          break;
      }
    }
    return result.fine();
  }

  public static JSONObject list(int page, int size, JSONArray filter) {
    String sec = Db.getSql("approval-list-sec");
    String exp = Db.getSql("approval-list-exp");
    Object type = Strings.get(filter, "type", false);
    Object status = Strings.get(filter, "status", false);
    if (null != type) {
      exp += " AND a.type = '" + type.toString() + "'";
    }
    if (null != status) {
      if (Consts.APPROVAL_CHECKED.equals(status.toString())) {
        exp += " AND a.status !='cancel' AND a.status !='checking''";
      } else {
        exp += " AND a.status = '" + status.toString() + "'";
      }
    }
    exp += " order by a.create_time desc ";
    Page<Record> pages = Db.paginate(page, size, sec, exp);
    return Models.compressPage(pages);
  }
}